package com.example.demo.service.imp;

import lombok.extern.log4j.Log4j2;
import com.example.demo.entity.AlarmPlatform;
import com.example.demo.entity.rep.RuleRep;
import com.example.demo.service.EsSearchService;
import com.example.demo.service.TemplateService;
import com.example.demo.service.WecomService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Log4j2
@Service
public class EsSearchServiceImp implements EsSearchService {

    @Autowired
    private WecomService wecomService;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private TemplateService templateService;
    /**
     * ES 搜索数据
     *
     * @param ruleRep
     */
    @Override
    public void searchDataFromEs(RuleRep ruleRep) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            log.info("Executing ES task: " + ruleRep.getName());
            Response response = restHighLevelClient.getLowLevelClient().performRequest(this.buildRequest(ruleRep));
            String jsonString = EntityUtils.toString(response.getEntity());
            Map<String, Object> resultMap = objectMapper.readValue(jsonString, Map.class);

            List<Map<String, Object>> hitsList = extractHitsList(resultMap);
            log.info("Execution ES result: " + hitsList);
            if (!hitsList.isEmpty()) {
                transformHitsList(hitsList);
                String template = templateService.generateTemplate(ruleRep.getName(), hitsList);
                log.info("Generated template: \n" + template);
                List<String> webComUrls = ruleRep.getAlarmPlatforms().stream()
                        .map(AlarmPlatform::getConfig)
                        .collect(Collectors.toList());
                if (!webComUrls.isEmpty()) {
                    wecomService.notify(webComUrls, template, ruleRep.getIsTest());
                }
            }
        } catch (IOException e) {
            log.error("Error executing ES task: {}", ruleRep.getName(), e);
        }
    }

    private Request buildRequest(RuleRep ruleRep) {
        Request request = new Request("POST", "/" + ruleRep.getDatasourceUuid() + "/_search");
        request.setJsonEntity(ruleRep.getSqlContent());
        return request;
    }

    private List<Map<String, Object>> extractHitsList(Map<String, Object> resultMap) {
        Map<String, Object> aggregationsList = (Map<String, Object>) resultMap.getOrDefault("aggregations", Collections.emptyMap());
        Map<String, Object> name = (Map<String, Object>) aggregationsList.getOrDefault("result", Collections.emptyMap());
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> buckets = (List<Map<String, Object>>) name.getOrDefault("buckets", Collections.emptyList());
        return buckets;
    }

    private void transformHitsList(List<Map<String, Object>> hitsList) {
        hitsList.forEach(hit -> {
            hit.put("name", hit.get("key"));
            hit.put("value", hit.get("doc_count"));
            hit.remove("key");
            hit.remove("doc_count");
        });
    }
}
